package com.data.platform.core.utils;

import cn.hutool.core.net.NetUtil;
import cn.hutool.system.SystemUtil;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.data.platform.core.enums.DataSize;
import com.data.platform.core.model.SystemMetrics;
import oshi.hardware.GlobalMemory;
import oshi.software.os.OSProcess;

import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 * 系统指标工具类
 */
public class SystemUtils {
    /**
     * cpu 信息
     */
    private static final CpuInfo CPU_INFO = OshiUtil.getCpuInfo();
    /**
     * 当前处理器
     */
    private static final OSProcess CURRENT_PROCESS = OshiUtil.getCurrentProcess();
    /**
     * 内存
     */
    private static final GlobalMemory MEMORY = OshiUtil.getMemory();
    /**
     * jvm
     */
    private static final Runtime RUNTIME = Runtime.getRuntime();

    /**
     * 格式化数字
     */
    private static final DecimalFormat DF = new DecimalFormat("##.##%");
    private static final NumberFormat NF = NumberFormat.getNumberInstance();

    static {
        NF.setMaximumFractionDigits(2);
        NF.setMinimumFractionDigits(2);
        NF.setRoundingMode(RoundingMode.HALF_UP);
        NF.setGroupingUsed(false);
    }

    public static SystemMetrics getSystemMetrics() {
        SystemMetrics systemMetrics = new SystemMetrics();

        fillBaseInfo(systemMetrics);
        fillCpuInfo(systemMetrics);
        fillMemoryInfo(systemMetrics);
        fillJvmMemoryInfo(systemMetrics);

        return systemMetrics;
    }

    private static void fillBaseInfo(SystemMetrics systemMetrics) {
        String computerName;
        try {
            computerName = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            computerName = "";
        }
        String os = SystemUtil.getOsInfo().getName();
        // mac地址
        String address = NetUtil.getLocalMacAddress();

        systemMetrics.setComputerName(computerName);
        systemMetrics.setMacAddress(address);
        systemMetrics.setOs(os);
    }

    private static void fillCpuInfo(SystemMetrics systemMetrics) {
        // cpu核数
        Integer cpuNum = CPU_INFO.getCpuNum();
        // cpu负载
        double cpuLoad = CPU_INFO.getUsed();

        systemMetrics.setCpuProcessors(cpuNum);
        systemMetrics.setCpuLoad(cpuLoad);
    }

    private static void fillMemoryInfo(SystemMetrics systemMetrics) {
        // 电脑的最大内存
        double maxMemory = miniDouble(DataSize.B.toGigabyte(MEMORY.getTotal()));
        // 电脑的已使用内存 = 最大内存 - 空闲内存
        double usedMemory = miniDouble(DataSize.B.toGigabyte(MEMORY.getTotal() - MEMORY.getAvailable()));

        systemMetrics.setUsedMemory(usedMemory);
        systemMetrics.setMaxMemory(maxMemory);
        systemMetrics.setMemoryUsage(miniDouble(usedMemory / maxMemory));
    }

    private static void fillJvmMemoryInfo(SystemMetrics systemMetrics) {
        // JVM内存信息(maxMemory指JVM能从操作系统获取的最大内存，即-Xmx参数设置的值，totalMemory指JVM当前持久的总内存)
        double jvmMaxMemory = miniDouble(DataSize.B.toGigabyte(RUNTIME.maxMemory()));
        double jvmUsedMemory = miniDouble(DataSize.B.toGigabyte(RUNTIME.totalMemory() - RUNTIME.freeMemory()));

        systemMetrics.setJvmUsedMemory(jvmUsedMemory);
        systemMetrics.setJvmMaxMemory(jvmMaxMemory);
        systemMetrics.setJvmMemoryUsage(miniDouble(jvmUsedMemory / jvmMaxMemory));
    }

    /**
     * 获取java.exe的绝对路径
     */
    public static String getJavaPath() {
        return CURRENT_PROCESS.getPath();
    }

    /**
     * cpu的当前值和阈值的比较
     *
     * @param cpuThreshold cpu阈值
     * @return 布尔类型
     */
    public static Boolean compareCpu(double cpuThreshold) {
        return Double.compare(CPU_INFO.getUsed(), cpuThreshold) >= 0 ? Boolean.TRUE : Boolean.FALSE;
    }

    private static double miniDouble(double origin) {
        return Double.parseDouble(NF.format(origin));
    }
}
